package com.service.gmall.common.config.threadpool;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author alpha
 * @className: AppThreadPoolAutoConfiguration
 * @date 2022/8/30 21:34
 * @Description
 */
@Configuration
@EnableConfigurationProperties(AppThreadPoolProperties.class)
public class AppThreadPoolAutoConfiguration {


    @Autowired
    AppThreadPoolProperties threadPoolProperties;
    @Value("${spring.application.name}")
    String applicationName;

    /**
     * int corePoolSize,  核心线程池： cpu核心数   4
     * int maximumPoolSize, 最大线程数：          8
     * long keepAliveTime,  线程存活时间
     * TimeUnit unit,      时间单位
     * BlockingQueue<Runnable> workQueue, 阻塞队列：大小需要合理
     * ThreadFactory threadFactory,  线程工厂。 自定义创建线程的方法
     * RejectedExecutionHandler handler
     * <p>
     * //  2000/s：队列大小根据接口吞吐量标准调整
     */
    @Bean
    public ThreadPoolExecutor coreExecutor() {
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                threadPoolProperties.getCorePoolSize(),
                threadPoolProperties.getMaximumPoolSize(),
                threadPoolProperties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(threadPoolProperties.getQueueCapacity()),
                new ThreadFactory() {//创建线程
                    int i = 0; //记录线程自增id

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName(applicationName + "[core-thread-" + i++ + "]");
                        return thread;
                    }
                },
                //生产环境用 CallerRuns，保证就算线程池满了，
                // 不能提交的任务，由当前线程自己以同步的方式执行
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        return poolExecutor;

    }

}
